#include "StdAfx.h"
#include "ExceptionHandler.h"
#include "Exception.h"
#include "CppException.h"
#include "SEHException.h"

void ExceptionHandler::attachToProcess() {
	SetUnhandledExceptionFilter(&ExceptionHandler::onException);
}

void ExceptionHandler::detachFromProcess() {
}

#define SEH_GENERAL_CASE(code) \
	case code:\
{ \
	pException = new SEHException(_T( #code ), (DWORD)pExceptionInfo->ExceptionRecord->ExceptionAddress, ctx); \
} \
	break

long __stdcall ExceptionHandler::onException(LPEXCEPTION_POINTERS pExceptionInfo) {
	if(!pExceptionInfo || !pExceptionInfo->ExceptionRecord)
		ExitProcess(0);

	LPCONTEXT ctx = pExceptionInfo->ContextRecord;

	Exception* pException = NULL;
	switch(pExceptionInfo->ExceptionRecord->ExceptionCode)
	{
	case 0xE06D7363:
		pException = new CPPException(pExceptionInfo);
		break;

	SEH_GENERAL_CASE(EXCEPTION_ACCESS_VIOLATION);
	SEH_GENERAL_CASE(EXCEPTION_INT_DIVIDE_BY_ZERO);
	SEH_GENERAL_CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
	SEH_GENERAL_CASE(EXCEPTION_BREAKPOINT);
	SEH_GENERAL_CASE(EXCEPTION_DATATYPE_MISALIGNMENT);
	SEH_GENERAL_CASE(EXCEPTION_FLT_DENORMAL_OPERAND);
	SEH_GENERAL_CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO);
	SEH_GENERAL_CASE(EXCEPTION_FLT_INEXACT_RESULT);
	SEH_GENERAL_CASE(EXCEPTION_FLT_INVALID_OPERATION);
	SEH_GENERAL_CASE(EXCEPTION_FLT_OVERFLOW);
	SEH_GENERAL_CASE(EXCEPTION_FLT_STACK_CHECK);
	SEH_GENERAL_CASE(EXCEPTION_FLT_UNDERFLOW);
	SEH_GENERAL_CASE(EXCEPTION_ILLEGAL_INSTRUCTION);
	SEH_GENERAL_CASE(EXCEPTION_IN_PAGE_ERROR);
	SEH_GENERAL_CASE(EXCEPTION_INT_OVERFLOW);
	SEH_GENERAL_CASE(EXCEPTION_INVALID_DISPOSITION);
	SEH_GENERAL_CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION);
	SEH_GENERAL_CASE(EXCEPTION_PRIV_INSTRUCTION);
	SEH_GENERAL_CASE(EXCEPTION_SINGLE_STEP);
	SEH_GENERAL_CASE(EXCEPTION_STACK_OVERFLOW);
	}

	if(pException != NULL)
		MessageBox(NULL, pException->getMessage().c_str(), "", MB_OK);

	ExitProcess(0);
}